﻿using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace FreeSql
{
    /// <summary>
    /// 非泛型 FreeSql 仓储
    /// </summary>
    public partial interface IFreeSqlRepository
    {
        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TEntity"> 实体类型 </typeparam>
        /// <typeparam name="TKey"> 主键类型 </typeparam>
        /// <returns> 仓储 </returns>
        IFreeSqlRepository<TEntity, TKey> Change<TEntity, TKey>()
            where TEntity : class, new();
    }

    /// <summary>
    /// </summary>
    /// <typeparam name="TEntity"> </typeparam>
    public partial interface IFreeSqlRepository<TEntity> : IFreeSqlRepository<TEntity, string> where TEntity : class, new()
    {
    }

    /// <summary>
    /// FreeSql 仓储接口定义
    /// </summary>
    /// <typeparam name="TEntity"> </typeparam>
    /// <typeparam name="TKey"> </typeparam>
    public partial interface IFreeSqlRepository<TEntity, TKey> : IBaseRepository<TEntity, TKey>
        where TEntity : class, new()
    {
        /// <summary>
        /// 动态数据库上下文
        /// </summary>
        dynamic DynamicDbContext { get; }

        /// <summary>
        /// 原生 Ado 对象
        /// </summary>
        IAdo Ado { get; }

        /// <summary>
        /// 实体集合
        /// </summary>
        ISelect<TEntity> Entities { get; }

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="whereExpression"> </param>
        /// <returns> </returns>
        long Count(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="whereExpression"> </param>
        /// <returns> </returns>
        Task<long> CountAsync(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"> </param>
        /// <returns> </returns>
        bool Any(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"> </param>
        /// <returns> </returns>
        Task<bool> AnyAsync(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="id"> </param>
        /// <returns> </returns>
        TEntity Single(dynamic id);

        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="id"> </param>
        /// <returns> </returns>
        Task<TEntity> SingleAsync(dynamic id);

        /// <summary>
        /// </summary>
        /// <param name="condition"> </param>
        /// <param name="predicate"> </param>
        /// <param name="ignoreQueryFilters"> </param>
        /// <returns> </returns>
        ISelect<TEntity> Where(bool condition, Expression<Func<TEntity, bool>> predicate, bool ignoreQueryFilters = false);

        /// <summary>
        /// 构建查询分析器
        /// </summary>
        /// <returns> </returns>
        ISelect<TEntity> AsQueryable();

        /// <summary>
        /// </summary>
        /// <param name="whereExpression"> </param>
        /// <returns> </returns>
        Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TChangeEntity"> 实体类型 </typeparam>
        /// <returns> 仓储 </returns>
        IFreeSqlRepository<TChangeEntity, string> Change<TChangeEntity>()
                where TChangeEntity : class, new();

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TChangeEntity"> 实体类型 </typeparam>
        /// <typeparam name="TChangeKey"> 主键类型 </typeparam>
        /// <returns> 仓储 </returns>
        IFreeSqlRepository<TChangeEntity, TChangeKey> Change<TChangeEntity, TChangeKey>()
                where TChangeEntity : class, new();

        /// <summary>
        /// </summary>
        /// <param name="entity"> </param>
        /// <param name="ignoreNullValues"> </param>
        /// <returns> </returns>
        int Update(TEntity entity, bool? ignoreNullValues);

        /// <summary>
        /// </summary>
        /// <param name="entity"> </param>
        /// <param name="ignoreNullValues"> </param>
        /// <returns> </returns>
        Task<int> UpdateAsync(TEntity entity, bool? ignoreNullValues);

        /// <summary>
        /// </summary>
        /// <param name="entity"> </param>
        /// <param name="propertyNames"> </param>
        /// <param name="ignoreNullValues"> </param>
        /// <returns> </returns>
        int UpdateExclude(TEntity entity, string[] propertyNames, bool? ignoreNullValues = null);

        /// <summary>
        /// </summary>
        /// <param name="entity"> </param>
        /// <param name="propertyNames"> </param>
        /// <param name="ignoreNullValues"> </param>
        /// <returns> </returns>

        Task<int> UpdateExcludeAsync(TEntity entity, string[] propertyNames, bool? ignoreNullValues = null);
    }
}
